# ======================================================================
#
# Copyright (C) ADN
# ADN::LIBRARY::SNMP::Liens Liens.pm
# Description:
#  - Recherche des liens entre équipements 
#
# ======================================================================

package ADN::LIBRARY::SNMP::Liens;

use strict;
use ADN::LIBRARY::SNMP::Gestion;
use ADN::LIBRARY::PING::Ping;
use ADN::CONF::Read;

# #######################
# CREAT OBJECT SELF + INIT. VAR.
# #######################
sub new
{
	my $self = shift;
  my $class = ref($self) || $self;
  return $self if ref $self;
  $self = bless {} => $class;
  my $conf = ADN::CONF::Read->new();
  if ($conf =~ m/^[-]1$/smx)
  {
    return -1;
  }
  my %LIENS = $conf->PING();
  $self->{boucle_ping} = $LIENS{boucle};
  $self->_init();
	undef $conf;
  return $self;
}

# #######################
# INIT.
# #######################
sub _init
{
  my $self = shift;

  $self->{BASE_OID} = '.1.3.6.1.2.1';
  %{$self->{SYSTEM}} = (
	      SystemeName => '.1.3.6.1.2.1.1.5.0',
        desc_int    => '.1.3.6.1.2.1.2.2.1.2',
	      mac_int     => '.1.3.6.1.2.1.2.2.1.6',
        int_arp     => '.1.3.6.1.2.1.3.1.1.1',
	      arp         => '.1.3.6.1.2.1.3.1.1.2',
	      ip_arp      => '.1.3.6.1.2.1.3.1.1.3',
	      ip_local    => '.1.3.6.1.2.1.4.20.1.1');
  $self->{requete} = ADN::LIBRARY::SNMP::Gestion->new($self->{BASE_OID}, \%{$self->{SYSTEM}});
	return;
}

# #######################
# MAIN
# #######################
sub start
{
  my $self = shift;
  (@{$self->{ip}}) = @_;

  $self->boucle_ping();
  if ((scalar (@{$self->{HOST}})) >= 1)
  {
    foreach my $host (@{$self->{HOST}})
    {
      %{$self->{result}} = $self->{requete}->start($host);
      $self->arp_double();
      $self->tableau($host);
      $self->tableau_ip();
      $self->tableau_ip2($host);
      $self->tableau_ip_local($host);
      $self->tableau_mac_local($host);
      $self->tableau_description($host);
      $self->tableau_mac_arp($host);
      $self->tableau_name($host);
    }
    $self->conception_liens();
    return ($self->to_string());
  }
  return;
}

# #######################
# TO STRING
# #######################
sub to_string
{
  my $self = shift;
  my ($ligne, $str);

  foreach $ligne (@{$self->{result2}})
  {
    $str .= $ligne;
  }
  $str =~ s/\,$//smx;
  return $str;
}

# #######################
# SET PING
# #######################
sub boucle_ping
{
  my $self = shift;
  my $boucle = $self->{boucle_ping};
  $self->{ping} = ADN::LIBRARY::PING::Ping->new();

  while ($boucle != 0)
  {
    $self->{ping}->start(@{$self->{ip}});
    $boucle--;
  }
  undef $boucle;
  @{$self->{HOST}} = $self->{ping}->start(@{$self->{ip}});
  undef $self->{ping};
  undef @{$self->{ip}};
  return;
}

# #######################
# TABLE IP ARP, 1 HOST
# #######################
sub tableau_ip2
{
  my $self = shift;
  my $boucle = $self->{result}{ip_arp};

  while ($boucle != 0)
  {
    unshift @{$self->{'ip_arp'.$_[0]}}, $self->{result}{'ip_arp.'.$boucle};
    $boucle--;
  }
  undef $boucle;
  return;
}

# #######################
# TABLE IP ARP
# #######################
sub tableau_ip
{
  my $self = shift;
  my $boucle = $self->{result}{ip_arp};
  my $ctr = 0;

  while ($boucle != 0)
  {
    foreach my $ligne (@{$self->{ip_arp}})
    {
      if ($ligne eq $self->{result}{'ip_arp.'.$boucle})
      {
        $ctr = 1;
      }
    }
    if ($ctr != 1)
    {
       push @{$self->{ip_arp}}, $self->{result}{'ip_arp.'.$boucle};
    }
    $ctr = 0;
    $boucle--;
  }
  undef $boucle;
  undef $ctr;
  return;
}

# #######################
# TABLE IP LOCAL, 1 HOST
# #######################
sub tableau_ip_local
{
  my $self = shift;
  my $boucle = $self->{result}{ip_local};

  while ($boucle != 0)
  {
    unshift @{$self->{'ip_local'.$_[0]}}, $self->{result}{'ip_local.'.$boucle};
    $boucle--;
  }
  undef $boucle;
  return;
}

# #######################
# TABLE MAC LOCAL, 1 HOST
# #######################
sub tableau_mac_local
{
  my $self = shift;
  my $boucle = $self->{result}{mac_int};

  while ($boucle != 0)
  {
    unshift @{$self->{'mac_int'.$_[0]}}, $self->{result}{'mac_int.'.$boucle};
    $boucle--;
  }
  undef $boucle;
  return;
}

# #######################
# TABLE DESC. 1 HOST
# #######################
sub tableau_description
{
  my $self = shift;
  my $boucle = $self->{result}{desc_int};
  my $ctr = 0;

  while ($boucle != 0)
  {
    foreach my $ligne (@{$self->{'desc_int'.$_[0]}})
    {
      if ($ligne eq $self->{result}{'desc_int.'.$boucle})
      {
        $ctr = 1;
      }
    }
    if ($ctr != 1)
    {
      unshift @{$self->{'desc_int'.$_[0]}}, $self->{result}{'desc_int.'.$boucle};
    }
    $ctr = 0;
    $boucle--;
  }
  undef $boucle;
  undef $ctr;
  return;
}

# #######################
# TABLE ARP, 1 HOST
# #######################
sub tableau_mac_arp
{
  my $self = shift;
  my $boucle = $self->{result}{arp};

  while ($boucle != 0)
  {
    unshift @{$self->{'arp'.$_[0]}}, $self->{result}{'arp.'.$boucle};
    $boucle--;
  }
  undef $boucle;
  return;
}

# #######################
# TABLE NAME HOST
# #######################
sub tableau_name
{
  my $self = shift;
  $self->{'SystemeName'.$_[0]} = $self->{result}{SystemeName};
  return;
}

# #######################
# CONCEP. LIENS
# #######################
sub conception_liens
{
  my $self = shift;
  @{$self->{result2}} = ();
  my ($inter1, $inter2);

  foreach my $host1 (@{$self->{ip_arp}})
  {
    foreach my $mac1 (@{$self->{$host1}})
    {
      foreach my $host2 (@{$self->{ip_arp}})
      {
        foreach my $mac2 (@{$self->{$host2}})
        {
          if (($host1 ne $host2) && $self->verif_ip_local($host1, $host2))
          {
            if ($self->verif_mac($host1, $mac2) && $self->verif_mac($host2, $mac1))
            {
              if ($self->lien_mac_ip($host1, $mac2) && $self->lien_mac_ip($host2, $mac1))
              {
                if ($self->verif_doublon($host1, $host2))
                {
                  $inter1 = $self->interface($host1, $mac2);
                  $inter2 = $self->interface($host2, $mac1);
                  push @{$self->{result2}}, "\\[\\{".$self->{'SystemeName'.$host1}.':'.$host1.':'.$mac2.':'.$inter1.'='.$self->{'SystemeName'.$host2}.':'.$host2.':'.$mac1.':'.$inter2."\\}\\],";
                }
              }
            }
          }
        }
      }
    }
  }
  return;
}

# #######################
# MAC, DESC OF INTERFACE
# #######################
sub interface
{
  my $self = shift;
  my $cnt = 0;
  my $mac;

  foreach $mac (@{$self->{'mac_int'.$_[0]}})
  {
    if ($_[1] eq $mac)
    {
      return (@{$self->{'desc_int'.$_[0]}}[$cnt]);
    }
    $cnt++;
  }
  undef $cnt;
  undef $mac;
  return;
}

# #######################
# TEST LIEN, IF EXIST OR NO EXIST
# #######################
sub verif_doublon
{
  my $self = shift;
  my $ligne;

  foreach $ligne (@{$self->{result2}})
  {
    if (($ligne =~ m/$_[0]/smx) && ($ligne =~ m/$_[1]/smx))
    {
      return 0;
    }
  }
  undef $ligne;
  return 1;
}

# #######################
# TEST LIEN, MAC AND IP
# #######################
sub lien_mac_ip
{
  my $self = shift;
  my $cnt = 0;

  foreach my $ip (@{$self->{'ip_arp'.$_[0]}})
  {
    if ($ip eq $_[0])
    {
      if (@{$self->{'arp'.$_[0]}}[$cnt] eq $_[1])
      {
        return 1;
      }
    }
    $cnt++;
  }
  return 0;
}

# #######################
# TEST IP LOOPBACK, EXIST OR NO
# #######################
sub verif_ip_local
{
  my $self = shift;

  foreach my $ip1 (@{$self->{'ip_local'.$_[0]}})
  {
    foreach my $ip2 (@{$self->{'ip_local'.$_[1]}})
    {
      if ($ip1 eq $ip2)
      {
        return 0;
      }
    }
  }
  return 1;
}

# #######################
# TEST MAC, MAC LOOPBACK
# #######################
sub verif_mac
{
  my $self = shift;
  my $cnt = 0;

  foreach my $mac (@{$self->{'mac_int'.$_[0]}})
  {
    if ($mac eq $_[1])
    {
      return 1;
    }
    $cnt++;
  }
  return 0;
}

# #######################
# TABLE ARP
# #######################
sub tableau
{
  my $self = shift;
  my ($host) = @_;
  my $boucle = $self->{result}{arp};

  while ($boucle != 0)
  {
    if ($self->{result}{'arp.'.$boucle} ne '')
    {
      push @{$self->{$host}}, $self->{result}{'arp.'.$boucle};
    }
    $boucle--;
  }
  undef $boucle;
  undef $host;
  return;
}

# #######################
# CLEAN DOUBLE ARP TABLE
# #######################
sub arp_double
{
  my $self = shift;
  my $boucle1 = $self->{result}{arp};
  my $boucle2;
  my $cnt = 0;

  while ($boucle1 != 0)
  {
    $boucle2 = $self->{result}{arp};
    while ($boucle2 != 0)
    {
      if ($self->{result}{'arp.'.$boucle2})
      {
        $cnt++;
      }
      $boucle2--;
    }
    if ($cnt < 1)
    {
      $self->{result}{'arp.'.$boucle1} = '';
      $cnt = 0;
    }
    $boucle1--;
  }
  undef $boucle1;
  undef $boucle2;
  undef $cnt;
  return;
}

# #######################
# DESTROY OBJECT
# #######################
sub DESTROY {
    my $self = shift;
    return;
}
1;
__END__